import os
import yaml
import logging
from pathlib import Path
from typing import Dict, Any, Optional

class ConfigManager:
    """
    配置管理类，用于统一管理应用程序的配置信息
    """

    DEFAULT_CONFIG = {}

    """
    功能:
    1. 加载和解析配置文件
    
    功能:
    1. 加载和解析配置文件
    2. 提供配置访问接口
    3. 配置验证
    4. 配置备份
    5. 默认配置处理
    """
    
    def __init__(self, config_path: Optional[str] = None):
        """
        初始化配置管理器
        
        参数:
            config_path: 配置文件路径，如果为None，将尝试从默认位置加载
        """
        self.logger = logging.getLogger(__name__)
        self.config_path = config_path
        self.config = None
        
        # 如果未提供配置路径，尝试从默认位置加载
        if not self.config_path:
            # 获取当前模块所在目录
            current_module_dir = os.path.dirname(os.path.abspath(__file__))
            # 假设配置文件在code目录下
            code_dir = os.path.dirname(current_module_dir)
            self.config_path = os.path.join(code_dir, "config.yaml")
        
        # 加载配置
        self.load_config()
    
    def load_config(self) -> Dict[str, Any]:
        """
        加载配置文件
        
        返回:
            配置字典
        """
        try:
            with open(self.config_path, 'r', encoding='utf-8') as config_file:
                self.config = yaml.safe_load(config_file)
            self.logger.info(f"配置文件加载成功: {self.config_path}")
        except Exception as e:
            self.logger.error(f"加载配置文件时发生错误: {e}")
            self.logger.warning("使用默认配置...")
            self.config = self.DEFAULT_CONFIG.copy()
        
        return self.config
    
    def get(self, key: str, default: Any = None) -> Any:
        """
        获取配置值
        
        参数:
            key: 配置键，支持点号分隔的嵌套键，如'data_source.base_dir'
            default: 如果键不存在，返回的默认值
            
        返回:
            配置值或默认值
        """
        if not self.config:
            self.load_config()
        
        # 处理嵌套键
        if '.' in key:
            parts = key.split('.')
            current = self.config
            for part in parts:
                if isinstance(current, dict) and part in current:
                    current = current[part]
                else:
                    return default
            return current
        
        # 处理顶级键
        return self.config.get(key, default)
    
    def get_section(self, section: str) -> Dict[str, Any]:
        """
        获取配置节
        
        参数:
            section: 配置节名称
            
        返回:
            配置节字典，如果节不存在则返回空字典
        """
        if not self.config:
            self.load_config()
        
        return self.config.get(section, {})
    
    def save_backup(self, output_dir: str) -> str:
        """
        将当前使用的配置保存为备份
        
        参数:
            output_dir: 输出目录
            
        返回:
            备份文件的路径
        """
        if not self.config:
            self.load_config()
        
        # 确保输出目录存在
        Path(output_dir).mkdir(parents=True, exist_ok=True)
        
        # 创建备份文件路径
        backup_path = os.path.join(output_dir, "used_config.yaml")
        
        # 保存配置
        try:
            with open(backup_path, 'w') as f:
                yaml.dump(self.config, f)
            self.logger.info(f"配置已备份到: {backup_path}")
        except Exception as e:
            self.logger.error(f"备份配置时发生错误: {e}")
        
        return backup_path
    
    def validate_data_paths(self) -> bool:
        """
        验证数据路径和必要文件是否存在
        
        返回:
            如果所有数据路径有效，返回True，否则返回False
        """
        # 获取项目根目录
        current_module_dir = os.path.dirname(os.path.abspath(__file__))
        code_dir = os.path.dirname(current_module_dir)
        project_root = os.path.dirname(code_dir)
        
        # 获取基础数据路径
        base_dir = self.get('data_source.base_dir')
        if base_dir.startswith('/'):
            # 如果是绝对路径，直接使用
            base_data_path = base_dir
        else:
            # 如果是相对路径，基于项目根目录
            base_data_path = os.path.join(project_root, base_dir)
        
        # 检查基础数据路径
        if not os.path.exists(base_data_path):
            self.logger.error(f"基础数据路径不存在: {base_data_path}")
            return False
        
        return True
    
    def setup_logging(self) -> None:
        """配置日志系统"""
        log_config = self.get_section('logging')
        log_level = log_config.get('level', 'INFO').upper()
        log_format = log_config.get('format', '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        
        # 配置根日志记录器
        logging.basicConfig(
            level=getattr(logging, log_level),
            format=log_format
        )